package models

import (
	"tms-server/driver"
	"tms-server/env"

	"fmt"

	"github.com/go-xorm/builder"
	"github.com/go-xorm/xorm"
)

// 权限管理

// 权限表
type Authority struct {
	Id     int64  `xorm:"pk autoincr int(11)"`
	Name   string `xorm:"varchar(50)"`
	Module string `xorm:"varchar(50)"`
	Page   string `xorm:"varchar(50)"`
	Button string `xorm:"varchar(50)"`
}

// 角色表
type Role struct {
	Id   int64  `xorm:"pk autoincr int(11)"`
	Name string `xorm:"varchar(50)"`
}

// 权限角色关系表 n~n
type RelRoleAuthority struct {
	RoleId      int64 `xorm:"int(11) index"`
	AuthorityId int64 `xorm:"int(11)"`
}

// 部门角色关系表 n~n
type RelDepRole struct {
	DepId  int64 `xorm:"int(11) index"`
	RoleId int64 `xorm:"int(11)"`
}

type DepRole struct {
	Dep  `xorm:"extends"`
	Role `xorm:"extends"`
}

type DepRoleAuthority struct {
	Authority        `xorm:"extends"`
	RelRoleAuthority `xorm:"extends"`
	Role             `xorm:"extends"`
	RelDepRole       `xorm:"extends"`
	Dep              `xorm:"extends"`
}

func (DepRole) TableName() string {
	return DBRole
}

func FindAuth(id int64, page string) (auth *Authority, err error) {
	auth = &Authority{Id: id}
	if id != 0 {
		auth.Id = id
	}
	if page != "" {
		auth.Page = page
	}
	found, err := driver.X.Get(auth)
	if err != nil {
		return nil, err
	}
	if !found {
		return nil, env.NotFound
	}
	return
}

func FindAuthes(modelName string) (authes []*Authority, err error) {
	authes = make([]*Authority, 0)
	query := make(map[string]interface{})
	if modelName != "" {
		query = builder.Eq{"module": modelName}
	}
	err = driver.X.
		Where(query).
		Asc("id").
		Find(&authes)
	return
}

// todo 等数据库填充差不多了再测
func FindAuthesByDepId(depId int64) (authes []*DepRoleAuthority, err error) {
	authes = make([]*DepRoleAuthority, 0)
	err = driver.X.Table(DBAuthority).
		Join("LEFT", DBRelRoleAuthority, fmt.Sprintf("%s.id = %s.authority_id", DBAuthority, DBRelRoleAuthority)).
		Join("LEFT", DBRole, fmt.Sprintf("%s.role_id = %s.id", DBRelRoleAuthority, DBRole)).
		Join("LEFT", DBDep, fmt.Sprintf("%s.dep_id = %s.id", DBRelDepRole, DBDep)).
		Where(builder.Eq{DBDep + ".depId": depId}).
		Cols(DBAuthority+".name", DBAuthority+".id", DBAuthority+".page", DBAuthority+".module").
		Find(authes)
	return
}

func (auth *Authority) Create() (err error) {
	id, err := driver.X.Insert(auth)
	if err != nil {
		return
	}
	auth.Id = id
	return
}

func (auth *Authority) Update() (err error) {
	if auth.Id == 0 {
		return env.NotFound
	}
	count, err := driver.X.Id(auth.Id).Update(auth)
	if err != nil {
		return
	}
	if count == 0 {
		return env.NoneAffect
	}
	return
}

func (auth *Authority) Del() (err error) {
	if auth.Id == 0 {
		return env.NotFound
	}
	count, err := driver.X.Id(auth.Id).Delete(auth)
	if err != nil {
		return
	}
	if count == 0 {
		return env.NoneAffect
	}
	return
}

func FindRoles() (depRoles []*DepRole, err error) {
	depRoles = make([]*DepRole, 0)
	err = driver.X.
		Join("LEFT", DBRelDepRole, fmt.Sprintf("%s.id = %s.role_id", DBRole, DBRelDepRole)).
		Join("LEFT", DBDep, fmt.Sprintf("%s.dep_id = %s.id", DBRelDepRole, DBDep)).
		Find(depRoles)
	return
}

func FindRole(name string) (depRole *DepRole, err error) {
	depRole = &DepRole{}
	found, err := driver.X.
		Join("LEFT", DBRelDepRole, fmt.Sprintf("%s.id = %s.role_id", DBRole, DBRelDepRole)).
		Join("LEFT", DBDep, fmt.Sprintf("%s.dep_id = %s.id", DBRelDepRole, DBDep)).
		Where(builder.Eq{DBDep + ".name": name}).
		Get(depRole)
	if err != nil {
		return nil, err
	}
	if !found {
		return nil, env.NotFound
	}
	return
}

func (role *Role) Create(session *xorm.Session) (err error) {
	var id int64
	if session != nil {
		id, err = session.Insert(role)
	} else {
		id, err = driver.X.Insert(role)
	}
	if err != nil {
		return
	}
	role.Id = id
	return
}

func (role *Role) Update(session *xorm.Session) (err error) {
	if role.Id == 0 {
		return env.NotFound
	}
	var count int64
	if session != nil {
		count, err = session.Where(builder.Eq{"id": role.Id}).Update(role)
	} else {
		count, err = driver.X.Where(builder.Eq{"id": role.Id}).Update(role)
	}
	if err != nil {
		return
	}
	if count == 0 {
		return env.NoneAffect
	}
	return
}

func (role *Role) Del(session *xorm.Session) (err error) {
	var count int64
	if session != nil {
		count, err = session.Where(builder.Eq{"id": role.Id}).Delete(role)
	} else {
		count, err = driver.X.Id(role.Id).Delete(role)
	}
	if err != nil {
		return
	}
	if count == 0 {
		return env.NoneAffect
	}
	return
}

func (role *Role) SaveAuth(authIds []int64) (err error) {
	if role.Id == 0 {
		return env.NotFound
	}
	return
}

func (dep *Dep) SaveRole(roleIds []int64) (err error) {
	if dep.Id == 0 {
		return env.NotFound
	}

	return
}

func (rel *RelDepRole) Create(session *xorm.Session) (err error) {
	if session != nil {
		_, err = session.Insert(rel)
	} else {
		_, err = driver.X.Insert(rel)
	}
	if err != nil {
		return
	}
	return
}

func CreateRelRoleAuth(rels ...interface{}) (err error) {
	_, err = driver.X.Insert(rels...)
	if err != nil {
		return
	}
	return
}

func (rel *RelDepRole) DelRelDepRoles(roleId int64) (err error) {
	_, err = driver.X.Where(builder.Eq{"role_id": roleId}).Delete(rel)
	if err != nil {
		return
	}
	return
}
